#include "txr_algo_dlm_cls.h"
#include <boost/filesystem.hpp>
#include <QSysInfo>
#include <QDebug>
#include <iostream>
#include <QCoreApplication>
#include <QDir>

#include "../tk_utility/tk_mutex.h"
#include "txr_algo_dlm_cls_impl.h"

using namespace tk;
// 全局互斥锁，用于保护DLL加载和卸载过程
static TkMutex g_dlm_mutex;

namespace txr_algo_dlm_cls
{
	// 定义函数指针类型，用于动态加载DLL中的函数
	typedef TxrAlgoDlmClsImpl* (*FuncCreateDlmClsObj)();    // 创建对象函数指针
	typedef void(*FuncDeleteDlmClsObj)(TxrAlgoDlmClsImpl*); // 删除对象函数指针
	
	/**
	 * @brief 构造函数
	 */
	TxrAlgoDlmCls::TxrAlgoDlmCls()
	{
	}

	/**
	 * @brief 析构函数，释放资源
	 */
	TxrAlgoDlmCls::~TxrAlgoDlmCls()
	{
		Release();
	}

	/**
	 * @brief 加载分类模型和对应的DLL
	 * @param cfg 模型配置信息
	 * @return 是否加载成功
	 */
	tk_bool TxrAlgoDlmCls::Load(st_dlm_cfg & cfg)
	{
		// 加锁保护
		TkMutexLocker lock(g_dlm_mutex);

		// 获取应用程序路径
		QString app_path = QCoreApplication::applicationDirPath();
		
		// 根据模型类型选择对应的DLL
		switch (GetDlmType(cfg))
		{
		case DLM_CLS_TYPE_V1:
			m_lib_dlm = new QLibrary(QDir::toNativeSeparators(app_path + "/txr_algo_dlm_cls_v1"));
			break;
		case DLM_CLS_TYPE_V2:
			m_lib_dlm = new QLibrary(QDir::toNativeSeparators(app_path + "/txr_algo_dlm_cls_v2"));
			break;
		case DLM_CLS_TYPE_V2_O:  // 添加OpenVINO版本
			m_lib_dlm = new QLibrary(QDir::toNativeSeparators(app_path + "/txr_algo_dlm_cls_v2_o"));
			break;
		default:
			return TK_FALSE;
		}

		// 加载DLL并获取函数指针
		if (m_lib_dlm)
		{
			// 加载DLL
			if (!m_lib_dlm->load())
			{
				qWarning() << "Library load fail: " << m_lib_dlm->errorString();
				return TK_FALSE;
			}
			// 获取创建对象函数
			FuncCreateDlmClsObj func = (FuncCreateDlmClsObj)(m_lib_dlm->resolve("CreateDlmClsObj"));
			if (func)
			{
				// 创建实现类对象
				m_dlm_obj = func();
				if (m_dlm_obj)
				{
					// 加载模型
					return m_dlm_obj->Load(cfg);
				}
			}
		}
		return TK_FALSE;
	}

	/**
	 * @brief 释放资源，包括DLL和实现类对象
	 */
	void TxrAlgoDlmCls::Release()
	{
		TkMutexLocker lock(g_dlm_mutex);
		if (m_lib_dlm)
		{
			// 获取删除对象函数
			FuncDeleteDlmClsObj func = (FuncDeleteDlmClsObj)(m_lib_dlm->resolve("DeleteDlmClsObj"));
			if (func)
			{
				// 删除实现类对象
				func(m_dlm_obj);
				m_dlm_obj = TK_NULL_PTR;
			}
			// 卸载DLL
			m_lib_dlm->unload();
			m_lib_dlm = TK_NULL_PTR;
		}
	}

	/**
	 * @brief 执行图像分类检测
	 * @param p_unit 检测单元数组
	 * @param size 数组大小
	 */
	void TxrAlgoDlmCls::Detect(st_detect_unit * p_unit, tk_int32 size)
	{
		TkMutexLocker lock(g_dlm_mutex);
		if (m_dlm_obj)
		{
			m_dlm_obj->Detect(p_unit, size);
		}
	}

	/**
	 * @brief 检查模型是否有效
	 * @return 是否有效
	 */
	tk_bool TxrAlgoDlmCls::IsVaild()
	{
		return m_dlm_obj != TK_NULL_PTR;
	}

	/**
	 * @brief 获取模型的batch size
	 * @return batch size大小
	 */
	tk_int32 TxrAlgoDlmCls::BatchSize()
	{
		TkMutexLocker lock(g_dlm_mutex);
		if (m_dlm_obj)
		{
			return m_dlm_obj->BatchSize();
		}
		return 0;
	}

	/**
	 * @brief 获取DLL类型
	 * @param cfg 模型配置信息
	 * @return DLL类型
	 */
	DLM_TYPE TxrAlgoDlmCls::GetDlmType(st_dlm_cfg & cfg)
	{
		// 如果配置中指定了类型，直接返回
		if (cfg.type != DLM_CLS_TYPE_UNKNOWN)
		{
			return cfg.type;
		}

		// 根据模型文件后缀判断类型
		using namespace boost::filesystem;
		{
			// 检查V1版本模型文件
			if (exists(path(std::string(cfg.file_path_name) + SUFFIX_V1)))
			{
				return DLM_CLS_TYPE_V1;
			}
			// 检查V2版本模型文件
			else if (exists(path(std::string(cfg.file_path_name) + SUFFIX_V2)))
			{
				return DLM_CLS_TYPE_V2;
			}
			// 检查V2_O版本模型文件
			else if (exists(path(std::string(cfg.file_path_name) + SUFFIX_V2_O)))
			{
				return DLM_CLS_TYPE_V2_O;
			}
		}
		return DLM_CLS_TYPE_UNKNOWN;
	}
}//namespace txr_algo_dlm_cls
